
import 'package:flutter/material.dart';

///
/// scroll_controller_demo.dart
/// [ScrollController] : https://api.flutter-io.cn/flutter/widgets/ScrollController-class.html
/// [Visibility] : https://api.flutter-io.cn/flutter/widgets/Visibility-class.html
/// [Visibility] 可用来控制 [FloatingActionButton] 的显示与隐藏
///

void main() => runApp(const ScrollControllerDemoWidget());

class ScrollControllerDemoWidget extends StatelessWidget {
  const ScrollControllerDemoWidget({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return const MyApp();
  }
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  State<StatefulWidget> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ScrollController? _controller;
  bool isToTop = false;

  @override
  @mustCallSuper
  void initState() {
    _controller = ScrollController();
    _controller?.addListener((){
      if (_controller!.offset > 1000) {
        setState(() {
          isToTop = true;
        });
      } else if (_controller!.offset < 300) {
        setState(() {
          isToTop = false;
        });
      }
    });
    super.initState();
  }

  // If this widget is always nested in a scrollable widget there is
  // no need to use a viewport because there will always be
  // enough vertical space for the children. In this case,
  // consider using a Column instead.
  // Otherwise, consider using the "shrinkWrap" property
  // (or a ShrinkWrappingViewport) to size the height of the viewport
  // to the sum of the heights of its children.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('ScrollController Demo')),
        body: ListView.builder(
          controller: _controller,
          itemCount: 100,
          itemBuilder: (context, index) => ListTile(title: Text('Index : $index')),
        ),
        floatingActionButton: Visibility(
          visible: isToTop,
          child: FloatingActionButton(
            child: const Icon(Icons.vertical_align_top),
            onPressed: (){
              if (isToTop) {
                _controller?.animateTo(
                  .0,
                  duration: const Duration(milliseconds: 200),
                  curve: Curves.ease
                );
              }
            },
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }
}

